package com.best.guanfengji.serial_port

import android.os.Handler
import android.os.HandlerThread
import android.os.Message
import android.serialport.SerialPort
import android.util.Log
import com.blankj.utilcode.util.LogUtils
import java.io.File

/**
 * author: shihao
 * date: 2021/3/3 16:16
 * description:
 */
class SerialPortManager private constructor() {

    private val TAG = javaClass.simpleName

    companion object {
        val instance: SerialPortManager by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
            SerialPortManager()
        }
    }

    private var serialPort: SerialPort? = null
    private var sendThread: HandlerThread? = null
    private var sendHandler: Handler? = null
    private val listenerList: MutableList<OnSerialPortDataListener> = arrayListOf()

    private var readThread: SerialPortReadThread? = null

    /**
     * 打开串口
     *  @return true 打开成功
     */
    fun openSerialPort(device: File): Boolean {
        if (serialPort == null) {
            try {
                serialPort = SerialPort(device, 115200)
                startSendThread()
                startReadThread()
            } catch (e: Exception) {
                e.printStackTrace()
                return false
            }
        }
        return true
    }

    /**
     * 添加数据监听
     */
    fun addOnSerialPortDataListener(listener: OnSerialPortDataListener) {
        Log.d(TAG, "addOnSerialPortDataListener")
        if (!listenerList.contains(listener))
            listenerList.add(listener)
    }

    /**
     * 移除数据监听
     */
    fun removeOnSerialPortDataListener(listener: OnSerialPortDataListener) {
        listenerList.remove(listener)
    }

    /**
     * 开启发送数据线程
     */
    private fun startSendThread() {
        sendThread = HandlerThread("sendThread")
        sendThread?.start()
        sendHandler = object : Handler(sendThread!!.looper) {
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                try {
                    val data = msg.obj as ByteArray
                    serialPort?.outputStream?.write(data)
                    Thread.sleep(10)
                    Log.d(TAG, "发送串口数据：${KTDataUtils.byteArrayToHex(data)}")
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
    }

    /**
     * 关闭发送数据线程
     */
    private fun stopSendThread() {
        sendHandler = null
        sendThread?.interrupt()
        sendThread?.quit()
        sendThread = null
    }

    /**
     * 开启读取数据线程
     */
    private fun startReadThread() {
        readThread = object : SerialPortReadThread(serialPort!!.inputStream) {

            override fun onRawDataReceived(text: String) {
                Log.d(TAG, "收到串口原始数据：$text")
            }

            override fun onDataReceived(text: String) {
                Log.d(TAG, "收到串口数据：$text")
                listenerList.forEach {
                    Log.d(TAG, "received Listener: ")
                    it.onDataReceived(text)
                }
            }
        }
        readThread?.start()
    }

    /**
     * 提示灯柱开启消毒
     * 7E 7E C0 01 01 E7 E7
     */
    private fun handTipsLampOpen(text: String) {
//        val array = text.split(" ")
//        if (array.size == 7 && array[0] == "7E" && array[1] == "7E") {
//            if (array[2] == "C0" && array[3] == "01" && array[4] == "01") {
//                val tipsLampOpenModel = Config.getTipsLampOpenConfig()
//                if (tipsLampOpenModel != null) {
//                    val intent = Intent()
//                    intent.putExtra("TipsLampOpenModel", Gson().toJson(tipsLampOpenModel))
//                    intent.action = TipsLampReceiver.TIPS_LAMP_RECEIVER_ACTION
//                    App.instance.applicationContext.sendBroadcast(intent)
//                } else {
//                    ToastUtils.showShort("未找到上次启动记录")
//                }
//            }
//        }
    }

    /**
     * 关闭读取数据线程
     */
    private fun stopReadThread() {
        readThread?.release()
        readThread = null
    }

    /**
     * 关闭串口
     */
    fun closeSerialPort() {
        serialPort?.tryClose()
    }

    /**
     * 发送字符串数据
     */
    fun sendStringData(text: String) {
        sendByteData(KTDataUtils.hexToByteArray(text))
    }

    /**
     * 发送字节数据
     */
    private fun sendByteData(byteArray: ByteArray) {
        if (serialPort != null && sendThread != null && sendHandler != null && readThread != null) {
            val message = Message.obtain()
            message.obj = byteArray
            sendHandler?.sendMessage(message)
        }
    }

    fun startSyncDataModel() {
        stopSendThread()
        stopReadThread()
    }

    fun stopSyncDataModel() {
        startSendThread()
        startReadThread()
    }

    /**
     * 同步发送字符串数据，会等待返回数据 ,需在子线程中执行
     *  @param timeout 超时时间，单位毫秒
     */
    fun sendStringDataSync(text: String, timeout: Int): String? {
        return sendByteDataSync(KTDataUtils.hexToByteArray(text), timeout)
    }

    fun sendStringDataSync(text: String): String? {
        return sendByteDataSync(KTDataUtils.hexToByteArray(text), 200)
    }

    fun sendByteDataSync(byteArray: ByteArray): String? {
        return sendByteDataSync(byteArray, 1000)
    }

    /**
     * 同步发送字节数据，会等待返回数据，需在子线程中执行
     */
    private fun sendByteDataSync(byteArray: ByteArray, timeout: Int): String? {
        serialPort?.outputStream?.write(byteArray)
        val array = ByteArray(1024)
        val start = System.currentTimeMillis()
        var data: String? = null
        var count = serialPort?.inputStream?.available()
        while (count == 0 && System.currentTimeMillis() < start + timeout) {
            Thread.sleep(10)
            count = serialPort?.inputStream?.available()
        }
        if (count == 0) {
            data = null
        } else {
            try {
                val size: Int? = serialPort?.inputStream?.read(array)
                if (size != null && size > 0) {
                    val readBytes = ByteArray(size)
                    System.arraycopy(array, 0, readBytes, 0, size)
                    data = KTDataUtils.byteArrayToHexTrim(readBytes)
                }
            } catch (e: Exception) {
                e.printStackTrace()
                data = null
            }
        }
        return data
    }


    interface OnSerialPortDataListener {

        /**
         * 收到串口数据，格式化为字符串（子线程中）
         */
        fun onDataReceived(text: String)
    }
}